﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.CampaignSystem.Election.SettlementClaimantDecision
// Assembly: TaleWorlds.CampaignSystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E85F8C15-4DF6-4E9C-A58A-29177E40D07A
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.CampaignSystem.dll

using Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.CharacterDevelopment;
using TaleWorlds.CampaignSystem.Settlements;
using TaleWorlds.Core;
using TaleWorlds.Library;
using TaleWorlds.Localization;
using TaleWorlds.SaveSystem;

#nullable disable
namespace TaleWorlds.CampaignSystem.Election
{
  public class SettlementClaimantDecision : KingdomDecision
  {
    [SaveableField(300)]
    public readonly Settlement Settlement;
    [SaveableField(301)]
    public readonly Clan ClanToExclude;
    [SaveableField(302)]
    private readonly Hero _capturerHero;

    internal static void AutoGeneratedStaticCollectObjectsSettlementClaimantDecision(
      object o,
      List<object> collectedObjects)
    {
      ((KingdomDecision) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
    }

    protected override void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
    {
      base.AutoGeneratedInstanceCollectObjects(collectedObjects);
      collectedObjects.Add((object) this.Settlement);
      collectedObjects.Add((object) this.ClanToExclude);
      collectedObjects.Add((object) this._capturerHero);
    }

    internal static object AutoGeneratedGetMemberValueSettlement(object o)
    {
      return (object) ((SettlementClaimantDecision) o).Settlement;
    }

    internal static object AutoGeneratedGetMemberValueClanToExclude(object o)
    {
      return (object) ((SettlementClaimantDecision) o).ClanToExclude;
    }

    internal static object AutoGeneratedGetMemberValue_capturerHero(object o)
    {
      return (object) ((SettlementClaimantDecision) o)._capturerHero;
    }

    public SettlementClaimantDecision(
      Clan proposerClan,
      Settlement settlement,
      Hero capturerHero,
      Clan clanToExclude)
      : base(proposerClan)
    {
      this.Settlement = settlement;
      this._capturerHero = capturerHero;
      this.ClanToExclude = clanToExclude;
    }

    public override bool IsAllowed()
    {
      return Campaign.Current.Models.KingdomDecisionPermissionModel.IsAnnexationDecisionAllowed(this.Settlement);
    }

    public override int GetProposalInfluenceCost()
    {
      return Campaign.Current.Models.DiplomacyModel.GetInfluenceCostOfAnnexation(this.ProposerClan);
    }

    public override TextObject GetSupportTitle()
    {
      TextObject supportTitle = new TextObject("{=Of7XnP5c}Vote for the new owner of {SETTLEMENT_NAME}");
      supportTitle.SetTextVariable("SETTLEMENT_NAME", this.Settlement.Name);
      return supportTitle;
    }

    public override TextObject GetGeneralTitle()
    {
      TextObject generalTitle = new TextObject("{=2qZ81jPG}Owner of {SETTLEMENT_NAME}");
      generalTitle.SetTextVariable("SETTLEMENT_NAME", this.Settlement.Name);
      return generalTitle;
    }

    public override TextObject GetSupportDescription()
    {
      TextObject supportDescription = new TextObject("{=J4UMplzb}{FACTION_LEADER} will decide who will own {SETTLEMENT_NAME}. You can give your support to one of the candidates.");
      supportDescription.SetTextVariable("FACTION_LEADER", this.DetermineChooser().Leader.Name);
      supportDescription.SetTextVariable("SETTLEMENT_NAME", this.Settlement.Name);
      return supportDescription;
    }

    public override TextObject GetChooseTitle()
    {
      TextObject chooseTitle = new TextObject("{=2qZ81jPG}Owner of {SETTLEMENT_NAME}");
      chooseTitle.SetTextVariable("SETTLEMENT_NAME", this.Settlement.Name);
      return chooseTitle;
    }

    public override TextObject GetChooseDescription()
    {
      TextObject chooseDescription = new TextObject("{=xzq78nVm}As {?IS_FEMALE}queen{?}king{\\?} you must decide who will own {SETTLEMENT_NAME}.");
      chooseDescription.SetTextVariable("IS_FEMALE", this.DetermineChooser().Leader.IsFemale ? 1 : 0);
      chooseDescription.SetTextVariable("SETTLEMENT_NAME", this.Settlement.Name);
      return chooseDescription;
    }

    protected override bool ShouldBeCancelledInternal()
    {
      return this.Settlement.MapFaction != this.Kingdom;
    }

    protected override bool CanProposerClanChangeOpinion() => true;

    public override float CalculateMeritOfOutcome(DecisionOutcome candidateOutcome)
    {
      SettlementClaimantDecision.ClanAsDecisionOutcome asDecisionOutcome = (SettlementClaimantDecision.ClanAsDecisionOutcome) candidateOutcome;
      Clan clan = asDecisionOutcome.Clan;
      float num1 = 0.0f;
      int num2 = 0;
      float num3 = Campaign.MapDiagonal + 1f;
      float maximumDistance = Campaign.MapDiagonal + 1f;
      foreach (Settlement fromSettlement in (List<Settlement>) Settlement.All)
      {
        if (fromSettlement.OwnerClan == asDecisionOutcome.Clan && fromSettlement.IsFortification && this.Settlement != fromSettlement)
        {
          num1 += fromSettlement.GetSettlementValueForFaction((IFaction) asDecisionOutcome.Clan.Kingdom);
          float distance;
          if (Campaign.Current.Models.MapDistanceModel.GetDistance(fromSettlement, this.Settlement, maximumDistance, out distance))
          {
            if ((double) distance < (double) num3)
            {
              maximumDistance = num3;
              num3 = distance;
            }
            else if ((double) distance < (double) maximumDistance)
              maximumDistance = distance;
          }
          ++num2;
        }
      }
      double num4 = (double) Campaign.AverageDistanceBetweenTwoFortifications * 1.5;
      float a = (float) (num4 * 0.25);
      float b = (float) num4;
      if ((double) maximumDistance < (double) Campaign.MapDiagonal)
        b = (float) (((double) maximumDistance + (double) num3) / 2.0);
      else if ((double) num3 < (double) Campaign.MapDiagonal)
        b = num3;
      float num5 = MathF.Pow((float) num4 / MathF.Max(a, MathF.Min(400f, b)), 0.5f);
      float num6 = clan.TotalStrength;
      if (this.Settlement.OwnerClan == clan && this.Settlement.Town != null && this.Settlement.Town.GarrisonParty != null)
      {
        num6 -= this.Settlement.Town.GarrisonParty.Party.TotalStrength;
        if ((double) num6 < 0.0)
          num6 = 0.0f;
      }
      float settlementValueForFaction = this.Settlement.GetSettlementValueForFaction((IFaction) asDecisionOutcome.Clan.Kingdom);
      int num7 = asDecisionOutcome.Clan.Leader == asDecisionOutcome.Clan.Kingdom.Leader ? 1 : 0;
      float num8 = num2 == 0 ? 30f : 0.0f;
      float num9 = num7 != 0 ? 60f : 0.0f;
      float num10 = this.Settlement.Town == null || this.Settlement.Town.LastCapturedBy != asDecisionOutcome.Clan ? 0.0f : 30f;
      float num11 = asDecisionOutcome.Clan.Leader == Hero.MainHero ? 30f : 0.0f;
      float num12 = asDecisionOutcome.Clan.Leader.Gold < 30000 ? MathF.Min(30f, (float) (30.0 - (double) asDecisionOutcome.Clan.Leader.Gold / 1000.0)) : 0.0f;
      return (float) (((double) clan.Tier * 30.0 + (double) num6 / 10.0 + (double) num8 + (double) num10 + (double) num9 + (double) num12 + (double) num11) / ((double) num1 + (double) settlementValueForFaction) * (double) num5 * 200000.0);
    }

    public override IEnumerable<DecisionOutcome> DetermineInitialCandidates()
    {
      Kingdom mapFaction = (Kingdom) this.Settlement.MapFaction;
      List<SettlementClaimantDecision.ClanAsDecisionOutcome> initialCandidates = new List<SettlementClaimantDecision.ClanAsDecisionOutcome>();
      foreach (Clan clan in (List<Clan>) mapFaction.Clans)
      {
        if (clan != this.ClanToExclude && !clan.IsUnderMercenaryService && !clan.IsEliminated && !clan.Leader.IsDead)
          initialCandidates.Add(new SettlementClaimantDecision.ClanAsDecisionOutcome(clan));
      }
      return (IEnumerable<DecisionOutcome>) initialCandidates;
    }

    public override Clan DetermineChooser() => ((Kingdom) this.Settlement.MapFaction).RulingClan;

    public override float DetermineSupport(Clan clan, DecisionOutcome possibleOutcome)
    {
      SettlementClaimantDecision.ClanAsDecisionOutcome asDecisionOutcome = (SettlementClaimantDecision.ClanAsDecisionOutcome) possibleOutcome;
      float num1 = asDecisionOutcome.InitialMerit * MathF.Clamp(1f + (float) clan.Leader.GetTraitLevel(DefaultTraits.Honor), 0.0f, 2f);
      float num2;
      if (asDecisionOutcome.Clan == clan)
      {
        float settlementValueForFaction = this.Settlement.GetSettlementValueForFaction((IFaction) clan);
        num2 = num1 + 0.2f * settlementValueForFaction * Campaign.Current.Models.DiplomacyModel.DenarsToInfluence();
      }
      else
      {
        float num3 = asDecisionOutcome.Clan != clan ? (float) FactionManager.GetRelationBetweenClans(asDecisionOutcome.Clan, clan) : 100f;
        int traitLevel = clan.Leader.GetTraitLevel(DefaultTraits.Calculating);
        num2 = num1 * MathF.Clamp(1f + (float) traitLevel, 0.0f, 2f) + num3 * 0.2f * (float) traitLevel;
      }
      int traitLevel1 = clan.Leader.GetTraitLevel(DefaultTraits.Calculating);
      float num4 = (float) (1.0 - (traitLevel1 > 0 ? 0.40000000596046448 - (double) MathF.Min(2, traitLevel1) * 0.10000000149011612 : 0.40000000596046448 + (double) MathF.Min(2, MathF.Abs(traitLevel1)) * 0.10000000149011612) * 1.5);
      return num2 * num4 * (clan == asDecisionOutcome.Clan ? 2f : 1f);
    }

    public override void DetermineSponsors(MBReadOnlyList<DecisionOutcome> possibleOutcomes)
    {
      foreach (DecisionOutcome possibleOutcome in (List<DecisionOutcome>) possibleOutcomes)
      {
        DecisionOutcome decisionOutcome;
        Clan clan = ((SettlementClaimantDecision.ClanAsDecisionOutcome) (decisionOutcome = possibleOutcome)).Clan;
        decisionOutcome.SetSponsor(clan);
      }
    }

    public override void ApplyChosenOutcome(DecisionOutcome chosenOutcome)
    {
      ChangeOwnerOfSettlementAction.ApplyByKingDecision(((SettlementClaimantDecision.ClanAsDecisionOutcome) chosenOutcome).Clan.Leader, this.Settlement);
    }

    protected override int GetInfluenceCostOfSupportInternal(Supporter.SupportWeights supportWeight)
    {
      switch (supportWeight)
      {
        case Supporter.SupportWeights.Choose:
        case Supporter.SupportWeights.StayNeutral:
          return 0;
        case Supporter.SupportWeights.SlightlyFavor:
          return 20;
        case Supporter.SupportWeights.StronglyFavor:
          return 60;
        case Supporter.SupportWeights.FullyPush:
          return 100;
        default:
          throw new ArgumentOutOfRangeException(nameof (supportWeight), (object) supportWeight, (string) null);
      }
    }

    public override TextObject GetSecondaryEffects()
    {
      return new TextObject("{=bHNU9uz2}All supporters gains some relation with the supported candidate clan and might lose with the others.");
    }

    public override void ApplySecondaryEffects(
      MBReadOnlyList<DecisionOutcome> possibleOutcomes,
      DecisionOutcome chosenOutcome)
    {
    }

    public override TextObject GetChosenOutcomeText(
      DecisionOutcome chosenOutcome,
      KingdomDecision.SupportStatus supportStatus,
      bool isShortVersion = false)
    {
      TextObject empty = TextObject.Empty;
      bool flag = ((SettlementClaimantDecision.ClanAsDecisionOutcome) chosenOutcome).Clan.Leader == this.Settlement.MapFaction.Leader;
      TextObject parent;
      if (supportStatus == KingdomDecision.SupportStatus.Majority & flag)
        parent = new TextObject("{=Zckbdm4Z}{RULER.NAME} of the {KINGDOM} takes {SETTLEMENT} as {?RULER.GENDER}her{?}his{\\?} fief with {?RULER.GENDER}her{?}his{\\?} council's support.");
      else if (supportStatus == KingdomDecision.SupportStatus.Minority & flag)
        parent = new TextObject("{=qa4FlTWS}{RULER.NAME} of the {KINGDOM} takes {SETTLEMENT} as {?RULER.GENDER}her{?}his{\\?} fief despite {?RULER.GENDER}her{?}his{\\?} council's opposition.");
      else if (flag)
      {
        parent = new TextObject("{=5bBAOHmC}{RULER.NAME} of the {KINGDOM} takes {SETTLEMENT} as {?RULER.GENDER}her{?}his{\\?} fief, with {?RULER.GENDER}her{?}his{\\?} council evenly split.");
      }
      else
      {
        switch (supportStatus)
        {
          case KingdomDecision.SupportStatus.Majority:
            parent = new TextObject("{=0nhqJewP}{RULER.NAME} of the {KINGDOM} grants {SETTLEMENT} to {LEADER.NAME} with {?RULER.GENDER}her{?}his{\\?} council's support.");
            break;
          case KingdomDecision.SupportStatus.Minority:
            parent = new TextObject("{=Ktpia7Pa}{RULER.NAME} of the {KINGDOM} grants {SETTLEMENT} to {LEADER.NAME} despite {?RULER.GENDER}her{?}his{\\?} council's opposition.");
            break;
          default:
            parent = new TextObject("{=l5H9x7Lo}{RULER.NAME} of the {KINGDOM} grants {SETTLEMENT} to {LEADER.NAME}, with {?RULER.GENDER}her{?}his{\\?} council evenly split.");
            break;
        }
      }
      parent.SetTextVariable("SETTLEMENT", this.Settlement.Name);
      StringHelpers.SetCharacterProperties("LEADER", ((SettlementClaimantDecision.ClanAsDecisionOutcome) chosenOutcome).Clan.Leader.CharacterObject, parent);
      StringHelpers.SetCharacterProperties("RULER", this.Settlement.MapFaction.Leader.CharacterObject, parent);
      parent.SetTextVariable("KINGDOM", this.Settlement.MapFaction.InformalName);
      parent.SetTextVariable("CLAN", ((SettlementClaimantDecision.ClanAsDecisionOutcome) chosenOutcome).Clan.Name);
      return parent;
    }

    public override DecisionOutcome GetQueriedDecisionOutcome(
      MBReadOnlyList<DecisionOutcome> possibleOutcomes)
    {
      return possibleOutcomes.OrderByDescending<DecisionOutcome, float>((Func<DecisionOutcome, float>) (t => t.Merit)).FirstOrDefault<DecisionOutcome>();
    }

    public class ClanAsDecisionOutcome : DecisionOutcome
    {
      [SaveableField(300)]
      public readonly Clan Clan;

      internal static void AutoGeneratedStaticCollectObjectsClanAsDecisionOutcome(
        object o,
        List<object> collectedObjects)
      {
        ((DecisionOutcome) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
      }

      protected override void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
      {
        base.AutoGeneratedInstanceCollectObjects(collectedObjects);
        collectedObjects.Add((object) this.Clan);
      }

      internal static object AutoGeneratedGetMemberValueClan(object o)
      {
        return (object) ((SettlementClaimantDecision.ClanAsDecisionOutcome) o).Clan;
      }

      public override TextObject GetDecisionTitle() => this.Clan.Leader.Name;

      public override TextObject GetDecisionDescription()
      {
        TextObject parent = new TextObject("{=QKIxepj5}The lordship of this fief should go to the {RECIPIENT.CLAN}");
        StringHelpers.SetCharacterProperties("RECIPIENT", this.Clan.Leader.CharacterObject, parent, true);
        return parent;
      }

      public override string GetDecisionLink() => this.Clan.Leader.EncyclopediaLink.ToString();

      public override ImageIdentifier GetDecisionImageIdentifier()
      {
        return new ImageIdentifier(CharacterCode.CreateFrom((BasicCharacterObject) this.Clan.Leader.CharacterObject));
      }

      public ClanAsDecisionOutcome(Clan clan) => this.Clan = clan;
    }
  }
}
